﻿using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace Narwhunderful.Aphelia.Framework.Net
{

    public abstract class BaseNarsock
    {

        public event EventHandler<NarsockStateChangedEventArgs> StateChanged;
        public event EventHandler<NarsockExceptionEventArgs> ExceptionReceived;

        bool _isClosing = false;

        Socket _socket = null;
        protected internal Socket Socket
        {
            get
            {
                return _socket;
            }
            set
            {
                _socket = value;
            }
        }

        int _port = 8080;
        public int Port
        {
            get
            {
                return _port;
            }
            set
            {
                _port = value;
            }
        }

        NarsockState _state = NarsockState.Closed;
        public NarsockState State
        {
            get
            {
                return _state;
            }
            protected set
            {
                _state = value;
            }
        }

        int _bufferSize = 8192;
        public int BufferSize
        {
            get
            {
                return _bufferSize;
            }
            set
            {
                _bufferSize = value;
            }
        }

        public void Close()
        {
            try
            {
                if (!_isClosing)
                {
                    _isClosing = true;
                    if (_state == NarsockState.Closed)
                    {
                        _isClosing = false;
                    }
                    else
                    {
                        OnStateChanged(new NarsockStateChangedEventArgs(NarsockState.Closing, _state));
                        DoClose();
                        _isClosing = false;
                        OnStateChanged(new NarsockStateChangedEventArgs(NarsockState.Closed, _state));
                    }
                }
            }
            catch (SocketException ex)
            {
                _isClosing = false;
                OnExceptionReceived(new NarsockExceptionEventArgs(ex));
            }
        }

        protected virtual void DoClose()
        {
            if (_socket != null) _socket.Close();
        }

        protected virtual void OnExceptionReceived(NarsockExceptionEventArgs e)
        {
            ExceptionReceived.SafeCrossThreadInvoke(this, e);
        }

        protected virtual void OnStateChanged(NarsockStateChangedEventArgs e)
        {
            if (_state != e.State)
            {
                _state = e.State;
                StateChanged.SafeCrossThreadInvoke(this, e);
            }
        }

    }

}
